﻿/*
 * ©2009-2010 XELF
 * http://xelf.info
 */

#if XNA || WINDOWS_PHONE
using Microsoft.Xna.Framework;
#endif

namespace XELF.Framework {
#if XNA || WINDOWS_PHONE
	public static partial class Vector2Helper {
#else
	public partial struct Vector2 {
#endif
		/// <summary>
		/// 変換してW=1に投影する。
		/// </summary>
		/// <param name="position"></param>
		/// <param name="matrix"></param>
		/// <param name="result"></param>
		public static void TransformCoordinate(ref Vector2 position, ref Matrix matrix, out Vector2 result) {
			result = new Vector2(
				position.X * matrix.M11 + position.Y * matrix.M21 + matrix.M41,
				position.X * matrix.M12 + position.Y * matrix.M22 + matrix.M42);
			var w = position.X * matrix.M14 + position.Y * matrix.M24 + matrix.M44;
			Vector2.Multiply(ref result, MathHelper.Rcp(w), out result);
		}
		/// <summary>
		/// 変換してW=1に投影する。
		/// </summary>
		/// <param name="position"></param>
		/// <param name="matrix"></param>
		/// <returns></returns>
		public static Vector2 TransformCoordinate(Vector2 position, Matrix matrix) {
			Vector2 result;
			TransformCoordinate(ref position, ref matrix, out result);
			return result;
		}
	}
}

namespace XELF.Framework {
#if XNA || WINDOWS_PHONE
	public static partial class Vector3Helper {
#else
	public partial struct Vector3 {
#endif
		/// <summary>
		/// 変換してW=1に投影する。
		/// </summary>
		/// <param name="position"></param>
		/// <param name="matrix"></param>
		/// <param name="result"></param>
		public static void TransformCoordinate(ref Vector3 position, ref Matrix matrix, out Vector3 result) {
			result = new Vector3(
				position.X * matrix.M11 + position.Y * matrix.M21 + position.Z * matrix.M31 + matrix.M41,
				position.X * matrix.M12 + position.Y * matrix.M22 + position.Z * matrix.M32 + matrix.M42,
				position.X * matrix.M13 + position.Y * matrix.M23 + position.Z * matrix.M33 + matrix.M43);
			var w = position.X * matrix.M14 + position.Y * matrix.M24 + position.Z * matrix.M34 + matrix.M44;
			Vector3.Multiply(ref result, MathHelper.Rcp(w), out result);
		}
		/// <summary>
		/// 変換してW=1に投影する。
		/// </summary>
		/// <param name="position"></param>
		/// <param name="matrix"></param>
		/// <returns></returns>
		public static Vector3 TransformCoordinate(Vector3 position, Matrix matrix) {
			Vector3 result;
			TransformCoordinate(ref position, ref matrix, out result);
			return result;
		}
	}
}

namespace XELF.Framework {
#if XNA || WINDOWS_PHONE
	public static partial class Vector4Helper {
#else
	public partial struct Vector4 {
#endif
		/// <summary>
		/// 変換してW=1に投影する。
		/// </summary>
		/// <param name="position"></param>
		/// <param name="matrix"></param>
		/// <param name="result"></param>
		public static void TransformCoordinate(ref Vector4 position, ref Matrix matrix, out Vector4 result) {
			result = new Vector4(
				position.X * matrix.M11 + position.Y * matrix.M21 + position.Z * matrix.M31 + position.W * matrix.M41,
				position.X * matrix.M12 + position.Y * matrix.M22 + position.Z * matrix.M32 + position.W * matrix.M42,
				position.X * matrix.M13 + position.Y * matrix.M23 + position.Z * matrix.M33 + position.W * matrix.M43,
				position.X * matrix.M14 + position.Y * matrix.M24 + position.Z * matrix.M34 + position.W * matrix.M44);
			Vector4.Multiply(ref result, MathHelper.Rcp(result.W), out result);
		}
		/// <summary>
		/// 変換してW=1に投影する。
		/// </summary>
		/// <param name="position"></param>
		/// <param name="matrix"></param>
		/// <returns></returns>
		public static Vector4 TransformCoordinate(Vector4 position, Matrix matrix) {
			Vector4 result;
			TransformCoordinate(ref position, ref matrix, out result);
			return result;
		}
	}

}
